package top.hmtools.controllers;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.ImageView;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.Callback;
import top.hmtools.GMContext;
import top.hmtools.base.ThreadLocalTools;
import top.hmtools.beans.DBConnectInfoBean;
import top.hmtools.beans.MapperXmlFileTempletBean;
import top.hmtools.callBacks.SqlConnectionListCallBack;
import top.hmtools.commons.AlertUtil;
import top.hmtools.enums.EDBType;
import top.hmtools.model.ResultModel;

public class IndexMainPaneController extends BaseController {
	@FXML
	private Accordion accordionLeft;
	@FXML
	TextField tf_tableName;
	@FXML
	TextField tf_savePath;
	@FXML
	Button btn_selectFile;
	@FXML
	TextField tf_pojoPackage;
	@FXML
	TextField tf_pojoName;
	@FXML
	TextField tf_daoPackage;
	@FXML
	TextField tf_daoName;
	@FXML
	CheckBox cb_isPojoCreatComment;
	@FXML
	CheckBox cb_isCamelVar;
	@FXML
	CheckBox cb_isOverrwiterToString;
	@FXML
	CheckBox cb_isDaoCreateComment;
	@FXML
	TextField tf_mapperXmlPackage;
	@FXML
	TextField tf_mapperXmlName;
	@FXML
	ComboBox<String> cb_dbType;
	@FXML
	ComboBox<String> cb_mapperXmlTemplet;
	@FXML
	ComboBox<String> cb_charset;
	@FXML
	Button btn_oneKeyGenerate;

	@Override
	public void initialize(URL location, ResourceBundle resources) {
		//将交互用的控件对象传入threadlocal
		this.putControlToThreadLocal();
		//初始化窗口左面版（数据库链接信息列表）
		this.initSqlConnectionsAtLeft();
		this.initDBType();
		this.initMapperXmlFileTemplet();
		this.initCharset();
	}

	/**
	 * 初始化窗口左边数据库链接列表信息
	 */
	private void initSqlConnectionsAtLeft() {
		// 情况折叠面板
		this.accordionLeft.getPanes().clear();

		// 遍历数据库类别
		for (EDBType item : EDBType.values()) {
			// 获取类别名称及内容数据，并初始化 TitledPane 折叠面板
			String name = item.getName();
			TreeView<String> treeView = new TreeView<>();
			treeView.setRoot(new TreeItem<>());
			treeView.setShowRoot(false);

			Callback<TreeView<String>, TreeCell<String>> defaultCellFactory = TextFieldTreeCell.forTreeView();
			treeView.setCellFactory(new SqlConnectionListCallBack(defaultCellFactory, treeView, this.dbManageService));

			ResultModel<DBConnectInfoBean> resultModel = this.dbManageService
					.getConncetionsByDBType(item.getTypeCode());
			if (resultModel.isStatusSuccess()) {
				List<DBConnectInfoBean> rows = resultModel.getRows();
				for (int ii = 0; rows != null && ii < rows.size(); ii++) {
					DBConnectInfoBean bean = rows.get(ii);
					TreeItem<String> tItem = new TreeItem<String>();
					tItem.setValue(bean.getName());
					ImageView icon = new ImageView("images/computer.png");
					icon.setFitHeight(16);
					icon.setFitWidth(16);
					icon.setUserData(bean);
					tItem.setGraphic(icon);
					tItem.setGraphic(icon);

					treeView.getRoot().getChildren().add(tItem);
				}
			}

			TitledPane titledPane = new TitledPane(name, treeView);

			// 鼠标右键菜单
			final ContextMenu contextMenu = new ContextMenu();
			MenuItem itemAddNew = new MenuItem("新增连接");
			itemAddNew.setOnAction(eventa -> {
				URL url = Thread.currentThread().getContextClassLoader()
						.getResource("viewFxml/AddNewDBConnection.fxml");
				FXMLLoader fxmlLoader = new FXMLLoader(url);

				Parent root = null;
				try {
					root = fxmlLoader.load();
				} catch (Exception e) {
					e.printStackTrace();
				}
				Scene scene = new Scene(root);

				Stage stage = new Stage();
				stage.setResizable(true);
				stage.setScene(scene);
				stage.setTitle("新增数据库链接");
				stage.show();
			});

			MenuItem itemRefresh = new MenuItem("刷新连接");
			itemRefresh.setUserData(item);
			itemRefresh.setOnAction(event -> {
				MenuItem itemSource = (MenuItem) event.getSource();
				EDBType dbType = (EDBType) itemSource.getUserData();
				reLoadDBConData(treeView, dbType.getTypeCode());
			});
			contextMenu.getItems().addAll(itemAddNew, itemRefresh);
			titledPane.setContextMenu(contextMenu);
			this.accordionLeft.getPanes().add(titledPane);
		}

	}
	
	/**
	 * 将本页的主要控件传入 threadlocal，以便其它类与方法调用（在同一个线程的情况下）
	 */
	private void putControlToThreadLocal(){
		ThreadLocalTools.put("tf_tableName", this.tf_tableName);
		ThreadLocalTools.put("tf_savePath", this.tf_savePath);
		ThreadLocalTools.put("tf_pojoPackage", this.tf_pojoPackage);
		ThreadLocalTools.put("tf_pojoName", this.tf_pojoName);
		ThreadLocalTools.put("tf_daoPackage", this.tf_daoPackage);

		ThreadLocalTools.put("tf_daoName", this.tf_daoName);
		ThreadLocalTools.put("tf_mapperXmlPackage", this.tf_mapperXmlPackage);
		ThreadLocalTools.put("tf_mapperXmlName", this.tf_mapperXmlName);

		ThreadLocalTools.put("cb_isPojoCreatComment", this.cb_isPojoCreatComment);
		ThreadLocalTools.put("cb_isCamelVar", this.cb_isCamelVar);
		ThreadLocalTools.put("cb_isOverrwiterToString", this.cb_isOverrwiterToString);
		ThreadLocalTools.put("cb_isDaoCreateComment", this.cb_isDaoCreateComment);

		ThreadLocalTools.put("cb_dbType", this.cb_dbType);
		ThreadLocalTools.put("cb_mapperXmlTemplet", this.cb_mapperXmlTemplet);
		ThreadLocalTools.put("cb_charset", this.cb_charset);
	}
	
	/**
     * 初始化数据库类型下拉框
    * 方法说明：                    initDataType
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
	private void initDBType() {
		this.cb_dbType.getItems().clear();
		ObservableList<String> dbTypes = FXCollections.observableArrayList();
		List<EDBType> list = new ArrayList<>();// 存储原始数据集
		int index = 0;
		for (EDBType item : EDBType.values()) {
			String name = item.getName();
			dbTypes.add(index, name);// 使选则列表项的索引与原始数据同步
			list.add(index, item);// 使选则列表项的索引与原始数据同步
			if (index == 0) {
				this.cb_dbType.setValue(name);
			}
			index++;
		}
		this.cb_dbType.setUserData(list);
		this.cb_dbType.setItems(dbTypes);
		
		//添加选择事件处理
		this.cb_dbType.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener<Object>() {
			@Override
			public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
				initMapperXmlFileTemplet();
			}
		});
	}
	
	private void initCharset(){
		ObservableList<String> charsets = this.cb_charset.getItems();
		charsets.clear();
		charsets.add("UTF-8");
		charsets.add("GBK");
		charsets.add("GB2312");
		this.cb_charset.setValue("UTF-8");
	}
	
	/**
	 * 初始化 mapper.xml模板文件下拉框
	 */
	private void initMapperXmlFileTemplet(){
		//获取当前选择的数据库类型代号
		int dbTypeIndex = this.cb_dbType.getSelectionModel().getSelectedIndex();
		if(dbTypeIndex<0){
			return;
		}
		List<EDBType> dbTypeList = (List<EDBType>) this.cb_dbType.getUserData();
		int dbTypeCode = dbTypeList.get(dbTypeIndex).getTypeCode();
		
		//填充数据
		ObservableList<String> mxtItems = this.cb_mapperXmlTemplet.getItems();
		mxtItems.clear();
		ResultModel<MapperXmlFileTempletBean> sqlPartsRM = this.mapperXmlTempletFileManageService.getSqlPartTempletsByDataType(dbTypeCode);
		if(sqlPartsRM.isStatusSuccess()){
			List<MapperXmlFileTempletBean> rows = sqlPartsRM.getRows();
			for(int ii=0;rows !=null && ii<rows.size();ii++){
				MapperXmlFileTempletBean bean = rows.get(ii);
				mxtItems.add(ii, bean.getName());
				if(ii==0){
					this.cb_mapperXmlTemplet.setValue(bean.getName());
				}
			}
			this.cb_mapperXmlTemplet.setItems(mxtItems);
			this.cb_mapperXmlTemplet.setUserData(rows);
		}
	}

	/**
	 * 重新加载数据
	 * 
	 * @param dbType
	 */
	private void reLoadDBConData(TreeView<String> treeView, int dbType) {
		treeView.getRoot().getChildren().clear();
		ResultModel<DBConnectInfoBean> resultModel = this.dbManageService.getConncetionsByDBType(dbType);
		if (resultModel.isStatusSuccess()) {
			List<DBConnectInfoBean> rows = resultModel.getRows();
			for (int ii = 0; rows != null && ii < rows.size(); ii++) {
				DBConnectInfoBean bean = rows.get(ii);
				TreeItem<String> tItem = new TreeItem<String>();
				tItem.setValue(bean.getName());
				ImageView icon = new ImageView("images/computer.png");
				icon.setFitHeight(16);
				icon.setFitWidth(16);
				icon.setUserData(bean);
				tItem.setGraphic(icon);
				tItem.setGraphic(icon);

				treeView.getRoot().getChildren().add(tItem);
			}
		}
	}

	@FXML
	public void doSelectFile(ActionEvent event) {
		DirectoryChooser directoryChooser = new DirectoryChooser();
        File selectedFolder = directoryChooser.showDialog(GMContext.getPrimaryStage());
        if (selectedFolder != null) {
            this.tf_savePath.setText(selectedFolder.getAbsolutePath());
        }
	}

	@FXML
	public void doOneKeyGenerate(ActionEvent event) {
		this.generateService.init();
		ResultModel<String> resultModel = this.generateService.doOneKeyGenerate();
		if(resultModel.isStatusSuccess()){
			AlertUtil.showInfoAlert(resultModel.getMessage());
		}else{
			AlertUtil.showWarnAlert(resultModel.getMessage());
		}
	}

	@FXML
	public void doViewPojo(ActionEvent event) {
		this.generateService.init();
		ResultModel<String> resultModel = this.generateService.generatePojo();
		this.showPreview(resultModel.getMessage(), "预览生成的pojo实体类");
	}

	@FXML
	public void doViewDao(ActionEvent event) {
		this.generateService.init();
		ResultModel<String> resultModel = this.generateService.generateDao();
		this.showPreview(resultModel.getMessage(), "预览生成的dao接口");
	}

	@FXML
	public void doViewMapperXml(ActionEvent event) {
		this.generateService.init();
		ResultModel<String> resultModel = this.generateService.generateMapperXml();
		this.showPreview(resultModel.getMessage(), "预览生成的mapper.xml文件");
	}
	
	/**
	 * 展示预览窗口
	 * @param content
	 * @param title
	 */
	private void showPreview(String content,String title){
		URL url = Thread.currentThread().getContextClassLoader().getResource("viewFxml/PreView.fxml");
		FXMLLoader fxmlLoader = new FXMLLoader(url);
		
		Parent root = null;
		try {
			root = fxmlLoader.load();
			PreViewController controller = fxmlLoader.getController();
			controller.setContent(content);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Scene scene = new Scene(root);
		
		Stage stage = new Stage();
		GMContext.setPrimaryStage(stage);
		stage.setWidth(800);
		stage.setHeight(600);
		stage.setResizable(true);
		stage.setScene(scene);
		stage.setTitle(title);
		stage.show();
	}

}
